<?php
namespace org\crawlgenie\models\dao;
use org\crawlgenie\application\base\Factory;
use org\crawlgenie\models\JobListingMeta;
use \Logger;
use \CGException;

/**
 *  Data Access Object for JobListing Metadata Model
 *
 *  @author $Author: jinsonxu@gmail.com $:
 *  $Date: 2014-11-16 10:39:12 +0000 (Sun, 16 Nov 2014) $:
 *  $Id: JobListingMetaDAO.php 16 2014-11-16 10:39:12Z jinsonxu@gmail.com $:
 *  @version $Rev: 16 $:
 *  @package crawlgenie.models
 *  @subpackage dao
 */

class JobListingMetaDAO {    

    public static function load($id) {
        $db = Factory::getDBConn();
        $metaObj = null;

        if(self::metaObjExists($id)) {

            $query = "select * from "._CG_REPOS_METADATA_TABLE." where "
                    ."id = ?";
            $queryValues = array($id);

            Logger::getLogger(__CLASS__)->debug(__METHOD__ . ': Meta Object Load Query: ' . print_r($query, true));
            Logger::getLogger(__CLASS__)->debug(__METHOD__ . ': Meta Object Load Values: ' . print_r($queryValues, true));

            $db->preparedQuery($query, $queryValues);
            $row = $db->getRow();

            $metaObj = new JobListingMeta($id);
            $metaObj->setAcl($row->acl);
            $metaObj->setAuthor($row->author);
            $metaObj->setBatchID($row->batchID);
            $metaObj->setBody($row->body);
            $metaObj->setCharacterSet($row->characterSet);
            $metaObj->setCrawlURI($row->crawlURI);
            $metaObj->setCreator($row->creator);
            $metaObj->setDateCreated($row->dateCreated);
            $metaObj->setFileSize($row->fileSize);
            $metaObj->setLastModified($row->lastModified);
            $metaObj->setPageCount($row->pageCount);
            $metaObj->setPath($row->path);
            $metaObj->setResourceType($row->resourceType);
            $metaObj->setTitle($row->title);            
            $metaObj->setContent(file_get_contents($metaObj->getPath()));
        }
        return $metaObj;
    }
    

    
    public static function getAllBatchRows($batchID, $author, $limit = null, $offset = null) {
        $db = Factory::getDBConn();
        $limitStatement = (null !== $limit && null !== $offset) ? " limit ".$limit." offset " . $offset : '';
        
        $query = "select * from " . _CG_REPOS_METADATA_TABLE . " where batch_id=? and author=? order by id" 
                . $limitStatement;
        $queryValues = array($batchID, $author);

        $db->preparedQuery($query, $queryValues);
        return $db->getResults();        
    }
    
    
    public static function getNumRecords($batchID, $author) {
        $db = Factory::getDBConn();
        
        $query = "select count(*) from " . _CG_REPOS_METADATA_TABLE . " where batch_id=? and author=?";
        $queryValues = array($batchID, $author);
        $db->preparedQuery($query, $queryValues);
        
        return $db->getVar();
    }
    
    
    /**
     * Saves the JobListing to a file on disk
     * 
     * @param JobListingMeta $metaObj
     * @throws CGException
     */
    public static function saveToDisk(JobListingMeta $metaObj) {
        if (!file_exists(dirname($metaObj->getPath()))) {
            mkdir(dirname($metaObj->getPath()), 0777, TRUE);
        }

        if(file_put_contents($metaObj->getPath(), $metaObj->getContent()) === FALSE) {
            Logger::getLogger(__CLASS__)->error(__METHOD__ . ': Unable to write to ' . $metaObj->getPath());
            throw new CGException(__METHOD__ . ': Unable to write to ' . $metaObj->getPath());
        }
    }
    
    
    /**
     * This function stores the job listing into the repository metadata in db 
     * after the crawler has obtained the raw data, and then saves the raw data 
     * onto the filesystem
     * 
     * @param JobListingMeta $metaObj
     */
    public static function store(JobListingMeta $metaObj) {
        $db = Factory::getDBConn();

        self::saveToDisk($metaObj);

        //JINSON NOTE: consider using exception handling to ensure file and metadata is in sync in case of failure in one or the other
        $metaObjInsertQuery = "insert into "._CG_REPOS_METADATA_TABLE."
                                (batch_id, instance_id, author, crawl_uri, resource_type, path, character_set, file_size, acl, 
                                date_created, creator, last_modified, page_count, title, body)
                                values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
        $metaObjInsertValues = array($metaObj->getBatchID(), $metaObj->getInstanceID(), $metaObj->getAuthor(),$metaObj->getCrawlURI(),
            $metaObj->getResourceType(),$metaObj->getPath(),$metaObj->getCharacterSet(),$metaObj->getFileSize(),
            $metaObj->getAcl(),$metaObj->getDateCreated(),$metaObj->getCreator(), $metaObj->getLastModified(), 
            $metaObj->getPageCount(), $metaObj->getTitle(), $metaObj->getBody());

        Logger::getLogger(__CLASS__)->debug(__METHOD__ . ': MetaObj Insertion Query: ' . print_r($metaObjInsertQuery, true));
        Logger::getLogger(__CLASS__)->debug(__METHOD__ . ': MetaObj Insertion Values: ' . print_r($metaObjInsertValues, true));

        $db->preparedQuery($metaObjInsertQuery, $metaObjInsertValues);        
    }
  
    
    
    
    public static function update(JobListingMeta $metaObj) {
        $db = Factory::getDBConn();
        
        // DELETE the old file/s from the repository
        $query = "select * from "._CG_REPOS_METADATA_TABLE." 
            where batch_id = ? and author = ? and crawl_uri = ? order by id desc";
        $db->preparedQuery($query, array($metaObj->getBatchID(), $metaObj->getAuthor(), $metaObj->getCrawlURI()));
        $rows = $db->getResults();
        $numRows = count($rows);

//            krumo($rows);
//            exit;
        Logger::getLogger(__CLASS__)->info(__METHOD__ . ': Number of duplicates: ' . $numRows);

        //we delete all related files on repository. And then also db metadata records other than the latest
        for($i=0;$i<$numRows;$i++) {
            $row = $rows[$i];

            Logger::getLogger(__CLASS__)->info(__METHOD__ . ': Deleting file ' . $row->path);
            if(!unlink($row->path)) {
                Logger::getLogger(__CLASS__)->info(__METHOD__ . ': Unable to delete file ' . $row->path);                    
            }

            if($i>0) {
                $query = "delete from " . _CG_REPOS_METADATA_TABLE . " where id=?";
                $db->preparedQuery($query, array($row->id));
                Logger::getLogger(__CLASS__)->info(__METHOD__ . ': Deletion query ' . $query . ', '. $row->id);
            }
        }
        
        // save onto filesystem
        self::saveToDisk($metaObj);


        $metaObjUpdateQuery = "update " . _CG_REPOS_METADATA_TABLE . " set batch_id=?, instance_id=?, author=?, "
                . "crawl_uri=?, resource_type=?, path=?, character_set=?, file_size=?, acl=?, "
                . "date_created=?, creator=?, last_modified=?, page_count=?, title=?, body=? "
                . "where batch_id=? and author=? and crawl_uri=?";
        $metaObjUpdateValues = array($metaObj->getBatchID(),$metaObj->getInstanceID(), $metaObj->getAuthor(),$metaObj->getCrawlURI(),
            $metaObj->getResourceType(),$metaObj->getPath(),$metaObj->getCharacterSet(),$metaObj->getFileSize(),
            $metaObj->getAcl(),$metaObj->getDateCreated(),$metaObj->getCreator(), $metaObj->getLastModified(), 
            $metaObj->getPageCount(), $metaObj->getTitle(), $metaObj->getBody(), $metaObj->getBatchID(),
            $metaObj->getAuthor(), $metaObj->getCrawlURI());

        $db->preparedQuery($metaObjUpdateQuery, $metaObjUpdateValues);

        Logger::getLogger(__CLASS__)->debug(__METHOD__ . ': MetaObj Update Query: ' . print_r($metaObjUpdateQuery, true));
        Logger::getLogger(__CLASS__)->debug(__METHOD__ . ': MetaObj Update Values: ' . print_r($metaObjUpdateValues, true));
    }
    
    
    


    public static function getMetaBatchIdFromDb($id) {
        $db = Factory::getDBConn();

        $query = "select batch_id from `"._CG_REPOS_METADATA_TABLE."`
                    where id = ?";
        $db->preparedQuery($query, array($id));

        return $db->getVar();
    }


    public static function metaObjExists($id) {
        $db = Factory::getDBConn();

        $metaObjExistsQuery = "select count(*) from "._CG_REPOS_METADATA_TABLE."
            where id = ?";
        $db->preparedQuery($metaObjExistsQuery, array($id));

        return ($db->getVar() > 0) ? true : false;
    }

    
    /**
     * Overloaded exist check method because it may be possible for 
     * us to get a duplicate resource in the same batch under some circumstances
     * eg. multi-page search results.
     * 
     * @param type $batchID
     * @param type $author
     * @param type $crawl_uri
     */
    public static function metaObjExists2($batchID, $author, $crawl_uri) {
        $db = Factory::getDBConn();

        $metaObjExistsQuery = "select count(*) from "._CG_REPOS_METADATA_TABLE." 
            where batch_id = ? and author = ? and crawl_uri = ?";
        $db->preparedQuery($metaObjExistsQuery, array($batchID, $author, $crawl_uri));

        return ($db->getVar() > 0) ? true : false;        
    }

    
    
    public function __call($name, $arguments) {
        if ($name === 'metaObjExists'){
            if(count($arguments) === 1 ){
                return $this->metaObjExists($arguments[0]);
            }
            if(count($arguments) === 3){
                return $this->metaObjExists2($arguments[0], $arguments[1], $arguments[2]);
            }
        }
    }
}
?>
